#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void *PrintHello(void *threadid)
{
    long tid;
    
    tid = (long) threadid;
    printf("Hello World! It's me, thread #%ld!\n", tid);
    pthread_exit((void*) threadid);
}

void *PrintGoodbye(void *threadid)
{
    long tid;
    tid = (long) threadid;
    printf("GoodBye! It's me, thread #%ld!\n", tid);
    pthread_exit((void*) threadid);
}


int main(int argc, char *argv[]) {
    pthread_t thread1;
    pthread_t thread2;
    pthread_attr_t attr;
    int rc;
    long t;
    void *status;

    /* Initialize and set thread detached attribute */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    printf("Main: creating thread1\n");
        rc = pthread_create(&thread1, &attr, PrintHello, (void *) t);
        if (rc) {
            printf("ERROR; return code from pthread_create() is % d\n", rc);
            exit(-1);
        }
    printf("Main: creating thread2\n");
        rc = pthread_create(&thread2, &attr, PrintGoodbye, (void *) t);
        if (rc) {
            printf("ERROR; return code from pthread_create() is % d\n", rc);
            exit(-1);
        }

    /* Free attribute and wait for the other threads */
    pthread_attr_destroy(&attr);
    rc = pthread_join(thread1, &status);
        if (rc) {
            printf("ERROR; return code from pthread_join() is % d\n", rc);
            exit(-1);
        }
        printf("Main: completed join with thread1 having a status of % ld\n", (long) status);
   
        pthread_attr_destroy(&attr);
    rc = pthread_join(thread2, &status);
        if (rc) {
            printf("ERROR; return code from pthread_join() is % d\n", rc);
            exit(-1);
        }
        printf("Main: completed join with thread2 having a status of % ld\n", (long) status);
    

    printf("Main: program completed. Exiting.\n");
    pthread_exit(NULL);
}
